#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>

#include "list.h"
#include "types.h"
#include "core_main.h"
#include "sys_main.h"

extern char sys_trace_data_file_name[FILENAME_MAX];
extern double sys_clock_rate;

extern struct list_head domain_list;

/*
 * dump the core data to files
 */
void dump_core_data_to_files( void )
{
	char file_name[FILENAME_MAX];
    FILE *outf;

    struct list_head* iter_domain, *iter_vcpu, *iter_time_slice;
    struct domain* pdomain;
    struct vcpu* pvcpu;
    struct time_slice* ptime_slice;
    int core_rec_sn=0;
	
	printf( "Dump core data to files now\n" );

    list_for_each( iter_domain, &domain_list ){
        pdomain = list_entry( iter_domain, struct domain, domain_list_elem );
        list_for_each( iter_vcpu, &pdomain->vcpu_list ){
            pvcpu = list_entry( iter_vcpu, struct vcpu, vcpu_list_elem );
			//reset the counter
			core_rec_sn=0;

			//open the output file now
			sprintf( file_name, "%s_%d_%d.txt", sys_trace_data_file_name, pdomain->domain_id, pvcpu->vcpu_id );
			printf( "Dumping time slices of <%d:%d> to file %s.\n", pdomain->domain_id, pvcpu->vcpu_id, file_name );

		    if( (outf = fopen( file_name, "w" )) == NULL ){
        		printf( "can not open the output file!\n" );
		        continue; 
		    }   

			//print title
			fprintf( outf, "SN\tPCPU\tSCHED_IN_TSC\tSCHED_OUT_TSC\tLEN(ms)\tSCHED_IN_TYPE\tSCHED_IN_DATA\tSCHED_OUT_TYPE\tSCHED_OUT_DATA\n" );

            list_for_each( iter_time_slice, &pvcpu->time_slice_list ){
                ptime_slice = list_entry( iter_time_slice, struct time_slice, time_slice_elem );
                fprintf( outf, "%d\t%d\t%llu\t%llu\t", 
                    core_rec_sn++, 
                    ptime_slice->pcpu_number,
                    ptime_slice->start_tsc, 
                    ptime_slice->term_tsc );
				//compute time slice length (in ms)
				fprintf( outf, "%5.1f\t", convert_tsc_to_ms( ptime_slice->term_tsc - ptime_slice->start_tsc ) );

				//sched in and out
			    switch( ptime_slice->sched_in_type ){
			        case SCHED_IN_NORMAL:
			            fprintf( outf, "SCHED_IN_NORMAL\t0\t" );
			            break;
			        case SCHED_IN_WAKE:
			            fprintf( outf, "SCHED_IN_WAKE\t%llu\t", ptime_slice->sched_in.wake_data.wake_tsc );
				        break;
			    }   

			    switch( ptime_slice->sched_out_type ){
			        case SCHED_OUT_NORMAL:
			            fprintf( outf, "SCHED_OUT_NORMAL\t0" );
			            break;
				    case SCHED_OUT_BLOCK:
			            fprintf( outf, "SCHED_OUT_BLOCK\t0" );
			            break;
			        case SCHED_OUT_YIELD:
			            fprintf( outf, "SCHED_OUT_YIELD\t%d", ptime_slice->sched_out.yield_data.yield_count );
			            break;
			        case SCHED_OUT_PREEMPT:
			            fprintf( outf, "SCHED_OUT_PREEMPT\t0" );
			            break;

				}

				//line ends
				fprintf( outf, "\n" );
            }
			//close the file
			fclose( outf );
        }
    }
}


